//
// Created by yoolo on 2020/11/8.
//

#include "slplayer.h"
#include "../utils/logger.h"

SLPlayer::SLPlayer(const char *p) {
    this->_path = p;
}

SLPlayer::~SLPlayer() {
    //onDestroy
    if (engineObject != NULL) {
        (*engineObject)->Destroy(engineObject);
    }
}

// 播放音频时的回调
static void AudioPlayerCallback(SLAndroidSimpleBufferQueueItf bufferQueueItf, void *context) {
    AudioContext *playerContext = (AudioContext *) context;
    if (!feof(playerContext->pflie)) {
        fread(playerContext->buffer, playerContext->bufferSize, 1, playerContext->pflie);
//        LOGI("czb", "read a frame audio data.");
        (*bufferQueueItf)->Enqueue(bufferQueueItf, playerContext->buffer,
                                   playerContext->bufferSize);
    } else {
        fclose(playerContext->pflie);
        delete playerContext->buffer;
    }
}

void SLPlayer::start() {
    //创建引擎
    if (engineEngine == NULL) {
        createEngine();
    } else {
        LOGD("czb", "engineEngine已经创建");
    }
//    创建混音器
    SLresult result;
    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObjext, 0, 0, 0);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;
    LOGD("czb", "混音器创建成功");

    result = (*outputMixObjext)->Realize(outputMixObjext, SL_BOOLEAN_FALSE);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;
    LOGD("czb", "混音器初始化成功");
    FILE *p_file = fopen(this->_path, "r");

    //创建播放器
    createAudioPlayer(engineEngine, outputMixObjext, playerObject);




    uint8_t *buffer = new uint8_t[BUFFER_SIZE];
    AudioContext *playerContext = new AudioContext(p_file, buffer, BUFFER_SIZE);
    result = (*playerBufferQueueItf)->RegisterCallback(playerBufferQueueItf,
                                                       AudioPlayerCallback,
                                                       playerContext);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;

    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;

    LOGD("czb", "开始播放");
    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    assert(SL_RESULT_SUCCESS == result);
    AudioPlayerCallback(playerBufferQueueItf, playerContext);
}

void SLPlayer::stop() {
    SLuint32 *state;
    (*playerPlay)->GetPlayState(playerPlay, state);
    SLresult r = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
    if(r==SL_RESULT_SUCCESS){
        LOGD("CZB","停止成功");
    } else{
        LOGE("CZB","停止失败");
    }
}


void SLPlayer::createEngine() {
    SLEngineOption engineOption[] = {
            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    };
    SLresult result;
    result = slCreateEngine(&engineObject, 1, engineOption, 0, NULL, NULL);
    assert(result == SL_RESULT_SUCCESS);

    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    assert(SL_RESULT_SUCCESS == result);

    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    assert(SL_RESULT_SUCCESS == result);
}

void SLPlayer::createAudioPlayer(SLEngineItf engineItf, SLObjectItf outputMixObject,
                                 SLObjectItf &audioObject) {
    SLDataLocator_AndroidBufferQueue SLDataSourceLocator = {
            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2
    };

    //PCM数据源格式
    SLDataFormat_PCM dataSourceFormat = {
            SL_DATAFORMAT_PCM, //格式类型
            2,//通道
            SL_SAMPLINGRATE_44_1,//采样率
            SL_PCMSAMPLEFORMAT_FIXED_16,//采样类型
            16,
            SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
            SL_BYTEORDER_LITTLEENDIAN
    };


    /**
     * 输出源
     */
    SLDataSource dataSource = {
            &SLDataSourceLocator,
            &dataSourceFormat
    };

    SLDataLocator_OutputMix dataSinkLocator = {
            SL_DATALOCATOR_OUTPUTMIX, //定位器类型
            outputMixObject //输出混合
    };

    /**
     * 输出目标
     */
    SLDataSink dataSink = {
            &dataSinkLocator,
            0
    };

    //需要的接口
    SLInterfaceID interfaceIds[] = {
            SL_IID_BUFFERQUEUE
    };
    SLboolean requiredInterfaces[] = {
            SL_BOOLEAN_TRUE
    };

    //创建音频播放对象
    SLresult result = (*engineEngine)->CreateAudioPlayer(
            engineEngine,
            &audioObject,
            &dataSource,
            &dataSink,
            1,
            interfaceIds,
            requiredInterfaces
    );
    assert(result == SL_RESULT_SUCCESS);
    (void) result;


    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);//是否一步
    assert(SL_RESULT_SUCCESS == result);
    (void) result;
    LOGD("czb", "播放器Realize");

    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
                                           &playerBufferQueueItf);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;
    LOGD("czb", "播放器获取缓冲接口");
}
